package com.securitydome05.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.ObjectUtils;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class LoginKaptcahFilter extends UsernamePasswordAuthenticationFilter {

    //默认验证码参数
    public static final String KAPTCHA_KEY = "kaptcha";


    public LoginKaptcahFilter(AuthenticationManager authenticationManager) {

        this.setUsernameParameter("uname");
        this.setPasswordParameter("pwd");
        this.setFilterProcessesUrl("/doLogin");
        this.setAuthenticationManager(authenticationManager);
        this.setKaptchaParameter("kaptcha");

        //成功
        this.setAuthenticationSuccessHandler(((request, response, authentication) -> {
            Map<String, Object> result=new HashMap<>();
            result.put("msg","登陆成功！");
            //用户信息
            result.put("authentication",authentication);
            response.setStatus(HttpStatus.OK.value());
            response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            String s = new ObjectMapper().writeValueAsString(result);
            response.getWriter().println(s);
        }));

        //失败
        this.setAuthenticationFailureHandler((request, response, exception) -> {
            //登录失败
            Map<String, Object> result=new HashMap<>();
            result.put("msg","登陆失败："+exception.getMessage());
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            String s = new ObjectMapper().writeValueAsString(result);
            response.getWriter().println(s);
        });
    }

    private String kaptchaParameter = KAPTCHA_KEY;

    public String getKaptchaParameter() {
        return kaptchaParameter;
    }

    public void setKaptchaParameter(String kaptchaParameter) {
        this.kaptchaParameter = kaptchaParameter;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

        if (!request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("不支持身份验证方法: " + request.getMethod());
        }
        //获取验证码
        try {
            //拿到请求过来的信息
            Map<String, String> userInfo = new ObjectMapper().readValue(request.getInputStream(), Map.class);
            //拿到前端请求的验证码
            String kaptcha = userInfo.get(KAPTCHA_KEY);
            String username = userInfo.get(getUsernameParameter());
            String password = userInfo.get(getPasswordParameter());

            //拿到正确的验证码
            String attribute = (String) request.getSession().getAttribute("kaptcha");
            if (!ObjectUtils.isEmpty(kaptcha) &&
                    !ObjectUtils.isEmpty(attribute) &&
                    kaptcha.equalsIgnoreCase(attribute)) {
                //验证用户
                UsernamePasswordAuthenticationToken authRequest = UsernamePasswordAuthenticationToken.unauthenticated(username, password);
                this.setDetails(request, authRequest);
                return this.getAuthenticationManager().authenticate(authRequest);
            }
            throw new UsernameNotFoundException("验证码错误！");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
